home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / Macintosh Sample Code / SC.016.OffSample / UFailure.inc1.p < prev    next >
Encoding:
Text File  |  1988-10-31  |  9.1 KB  |  395 lines  |  [TEXT/MPS ]

  1. {------------------------------------------------------------------------------
  2. #
  3. #    Apple Macintosh Developer Technical Support
  4. #
  5. #    Exception handling for MPW Pascal, MacApp and MPW C
  6. #
  7. #    UFailure (aka Signals) - “Exceptional code, with a few exceptions.”
  8. #
  9. #    UFailure.inc1.p    -    Pascal source - the IMPLEMENTATION
  10. #
  11. #    Copyright © 1985-1988 Apple Computer, Inc.
  12. #    All rights reserved.
  13. #
  14. #    Versions:    1.0                    11/88
  15. #
  16. #    Components:    UFailure.p            November 1, 1988
  17. #                UFailure.h            November 1, 1988
  18. #                UFailure.inc1.p        November 1, 1988
  19. #                UFailure.a            November 1, 1988
  20. #                TestCignal.c        November 1, 1988
  21. #                TestCignal.make        November 1, 1988
  22. #                TestSignal.p        November 1, 1988
  23. #                TestSignal.make        November 1, 1988
  24. #
  25. #    UFailure (or Signals) is a set of exception handling routines suitable for
  26. #    use with MacApp, MPW C, and MPW Pascal. It is a jazzed-up version of the MacApp
  27. #    UFailure unit. There is a set of C interfaces to it as well.
  28. #
  29. ------------------------------------------------------------------------------}
  30.  
  31.  
  32. VAR
  33.     {$PUSH}
  34.     {$Z+}    {make gTopHandler accessable to assembly code}
  35.     gTopHandler:        PFailInfo;    {linked list of failure handlers}
  36.      gInitHandler:        ProcPtr;
  37.     {$POP}
  38.  
  39.  
  40. PROCEDURE InitUFailure; EXTERNAL;
  41.     { Allocates the heap block for CatchSignals and initializes the global
  42.         variables used by the unit. }
  43.  
  44. PROCEDURE InitSignals; EXTERNAL;
  45.     { Calls InitUFailure. It also sets up the A6 for the main level of Pascal,
  46.         so it must be called from the outermost level of Pascal. }
  47.  
  48.  
  49. FUNCTION CatchSignal: INTEGER; EXTERNAL;
  50.     { Until the procedure which encloses this call returns, this will catch
  51.         subsequent Signal calls, returning the code passed to Signal.  When
  52.         CatchSignal is encountered initially, it returns a code of zero.  These
  53.         calls may "nest"; i.e. you may have multiple CatchSignals in one procedure.
  54.         Each nested CatchSignal call uses 72 bytes of heap space.
  55.         If you signal with SignalMessage and pass in a non-zero message you should use
  56.         CatchHandler instead so you have a way of getting at the message. }
  57.  
  58.  
  59. PROCEDURE FreeSignal; EXTERNAL;
  60.     { This undoes the effect of the last CatchSignal.  A Signal will then invoke
  61.         the CatchSignal prior to the last one. }
  62.  
  63.  
  64. PROCEDURE Signal(code: INTEGER); EXTERNAL;
  65.     { Returns control to the point of the last CatchSignal.  The program will
  66.         then behave as though that CatchSignal had returned with the code parameter
  67.         supplied to Signal. If CatchHandler is catching, the message parameter will be 0. }
  68.  
  69.  
  70. PROCEDURE SignalMessage(code: INTEGER; message: LONGINT); EXTERNAL;
  71.     { Returns control to the point of the last CatchSignal/CatchFailures.
  72.         If CatchFailures is catching, the message parameter will be returned. }
  73.         
  74.         
  75. {-----------------------------------+
  76. |    MacApp stuff                    |
  77. +-----------------------------------}
  78.  
  79.  
  80. {-----------------------------------+ 
  81. |    External Declarations            |
  82. +-----------------------------------}
  83. PROCEDURE CatchFailures (VAR fi: FailInfo;
  84.                         PROCEDURE Handler(e: INTEGER; m: LONGINT)); EXTERNAL;
  85.  
  86. PROCEDURE DoFailure(pf: PFailInfo); EXTERNAL;
  87.  
  88. {-----------------------------------+ 
  89. |    CallInitHandler                    |
  90. +-----------------------------------}
  91. PROCEDURE CallInitHandler (error: INTEGER; message: LONGINT; p: ProcPtr);
  92.         INLINE    $205F,        {MOVE.L        (A7)+,A0    }
  93.                 $4E90;        {JMP        (A0)        }
  94.  
  95. {$IFC UsingMacApp}
  96. {$S MAMain}
  97. {$ENDC}
  98. {-----------------------------------+ 
  99. |    FailMemError                    |
  100. +-----------------------------------}
  101. PROCEDURE FailMemError;
  102. VAR
  103.     e:    OSErr;
  104. {$IFC qDebug}
  105.     s:        Str255;
  106. {$ENDC}
  107. BEGIN
  108.     e := MemError;
  109.  
  110. {$IFC UsingMacApp}
  111. {$IFC qDebug}
  112.     IF gAskFailure AND (e = noErr) AND CanReadLn THEN
  113.         BEGIN
  114. {$%+}
  115.         GetMethodName(%_GetA6+4, s);
  116. {$%-}
  117.         e := ReadInteger(CONCAT('FailMemError called by ', s, '.  Enter return error: '));
  118.         END;
  119. {$ENDC qDebug}
  120. {$ENDC UsingMacApp}
  121.  
  122.     IF e <> noErr THEN
  123.         Failure(e, 0);
  124. END {FailMemError};
  125.  
  126.  
  127. {$IFC UsingMacApp}
  128. {$S MAMain}
  129. {$ENDC}
  130. {-----------------------------------+ 
  131. |    FailNIL                            |
  132. +-----------------------------------}
  133. PROCEDURE FailNIL (p: UNIV Ptr);
  134. BEGIN
  135.     { no check for gAskFailure here, since we do this when objects are created. }
  136.     IF p = NIL THEN
  137.         Failure(memFullErr, 0);
  138. END {FailNIL};
  139.  
  140.  
  141. {$IFC UsingMacApp}
  142. {$S MAMain}
  143. {$ENDC}
  144. {-----------------------------------+ 
  145. |    FailNewMessage                    |
  146. +-----------------------------------}
  147. PROCEDURE FailNewMessage (error: INTEGER; oldMessage, newMessage: LONGINT);
  148. BEGIN
  149.     IF oldMessage = 0 THEN
  150.         oldMessage := newMessage;
  151.     Failure(error, oldMessage);
  152. END {FailNewMessage};
  153.  
  154.  
  155. {$IFC UsingMacApp}
  156. {$S MAMain}
  157. {$ENDC}
  158. {-----------------------------------+ 
  159. |    FailOSErr                        |
  160. +-----------------------------------}
  161. PROCEDURE FailOSErr (error: INTEGER);
  162.  
  163. {$IFC qDebug}
  164. VAR
  165.     s:        Str255;
  166. {$ENDC}
  167.  
  168. BEGIN
  169. {$IFC UsingMacApp}
  170. {$IFC qDebug}
  171.     IF gAskFailure AND (error = noErr) AND CanReadLn THEN
  172.         BEGIN
  173. {$%+}
  174.         GetMethodName(%_GetA6+4, s);
  175. {$%-}
  176.         error := ReadInteger(CONCAT('FailOSErr called by ', s, '.  Enter return error: '));
  177.         END;
  178. {$ENDC qDebug}
  179. {$ENDC UsingMacApp}
  180.  
  181.     IF error <> noErr THEN
  182.         Failure(error, 0);
  183. END {FailOSErr};
  184.  
  185.  
  186. {$IFC UsingMacApp}
  187. {$S MAMain}
  188. {$ENDC}
  189. {-----------------------------------+ 
  190. |    FailResError                    |
  191. +-----------------------------------}
  192. PROCEDURE FailResError;
  193. VAR
  194.     e:    OSErr;
  195. {$IFC qDebug}
  196.     s:        Str255;
  197. {$ENDC}
  198. BEGIN
  199.     e := ResError;
  200.  
  201. {$IFC UsingMacApp}
  202. {$IFC qDebug}
  203.     IF gAskFailure AND (e = noErr) AND CanReadLn THEN
  204.         BEGIN
  205. {$%+}
  206.         GetMethodName(%_GetA6+4, s);
  207. {$%-}
  208.         e := ReadInteger(CONCAT('FailResError called by ', s, '.  Enter return error: '));
  209.         END;
  210. {$ENDC qDebug}
  211. {$ENDC UsingMacApp}
  212.  
  213.     IF e <> noErr THEN
  214.         Failure(e, 0);
  215. END {FailResError};
  216.  
  217.  
  218. {$IFC UsingMacApp}
  219. {$S MAMain}
  220. {$ENDC}
  221. {-----------------------------------+ 
  222. |    Failure                            |
  223. +-----------------------------------}
  224. PROCEDURE Failure (error: INTEGER; message: LONGINT);
  225. VAR
  226.     pf:     PFailInfo;
  227.     ih:     ProcPtr;
  228.     pc:        LONGINT;
  229. {$IFC UsingMacApp}
  230. {$IFC qDebug}
  231.     cl:     String8;
  232.     me:     String8;
  233.     seg:    INTEGER;
  234.     who:    STRING[17];
  235. {$ENDC qDebug}
  236. {$ENDC UsingMacApp}
  237. BEGIN
  238.     pf := gTopHandler;
  239.  
  240.     IF pf <> NIL THEN
  241.         BEGIN
  242. {$IFC UsingMacApp}
  243. {$IFC qDebug}
  244.         pc := pf^.whoPC;
  245.         GetProcname(LONGINT(@pc), cl, me);
  246.         who := CONCAT(cl, '.', me);
  247.         IF cl = kSpace8 THEN
  248.             who[9] := ' ';
  249.         
  250.         Writeln('Failure caught by ', who);
  251.         Writeln('        error = ', error:1, ' message = ', message:1,
  252.                 ' (', BSR(message, 16):1, '/', BAND(message, $0000FFFF):1, ')');
  253. {$ENDC qDebug}
  254. {$ENDC UsingMacApp}
  255.  
  256.     {* RBB removed the line 
  257.         gTopHandler := pf^.nextInfo;
  258.       on 9/26/88 since DoFailure calls FreeSignal first thing *}
  259.         pf^.error := error;
  260.         pf^.message := message;
  261.         DoFailure(pf);            {Go execute the failure handler}
  262.         END
  263.     ELSE IF gInitHandler <> NIL THEN
  264.         BEGIN
  265.         ih := gInitHandler;
  266.         gInitHandler := NIL;
  267.         CallInitHandler(error, message, ih);
  268.  
  269.         ExitToShell;
  270.         END
  271.     ELSE
  272.         BEGIN
  273. {$IFC UsingMacApp}
  274. {$IFC qDebug}
  275.         ProgramBreak('Failure called, but no handler!');
  276. {$ENDC qDebug}
  277. {$ELSEC}
  278.     Debugger;
  279. {$ENDC UsingMacApp}
  280.         END;
  281. END {Failure};
  282.  
  283.  
  284. {$IFC UsingMacApp}
  285. {$IFC qDebug}
  286. {$IFC qTrace}{$D+}{$ENDC}
  287. {$S MADebug}
  288. {-----------------------------------+ 
  289. |    ProgramBreak                    |
  290. +-----------------------------------}
  291. PROCEDURE ProgramBreak (grievance: Str255);
  292.     { ProgramBreak: Your app can call this when it comes to a situation that you do not expect
  293.         and cannot handle gracefully.  It beeps and displays a message.  If called before
  294.         there is a WriteLn window, it calls OBJFail, which goes into an infinite loop.
  295.         Otherwise, it enters our debugger. }
  296. VAR
  297.     synthRec:    RECORD
  298.                 mode:        INTEGER;
  299.                 triplet:    Tone;
  300.                 endTriplet: Tone;
  301.                 END;
  302.  
  303. BEGIN
  304. {$IFC FALSE}
  305.     WITH synthRec, triplet DO
  306.         BEGIN
  307.         mode := swMode;
  308.  
  309.         count := 445;
  310.         amplitude := 100;
  311.         duration := 25;
  312.  
  313.         endTriplet.count := 0;
  314.         endTriplet.amplitude := 0;
  315.         endTriplet.duration := 0;
  316.         END;
  317.  
  318.     StartSound(@synthRec, SIZEOF(synthRec), Pointer(-1));
  319. {$ENDC}
  320.     SysBeep(2);
  321.  
  322.     WWForceOutput(forceOn, forceUnchanged);
  323.     WriteLn('ProgramBreak: ', grievance);
  324.     WWEndForce;
  325.  
  326. {$IFC qTrace}
  327.     TRCBreak;
  328. {$ELSEC}
  329.     OBJFail(kFailNone);
  330. {$ENDC}
  331. END {ProgramBreak};
  332. {$IFC qTrace}{$D++}{$ENDC}
  333.  
  334.  
  335. {$IFC qTrace}{$D+}{$ENDC}
  336. {$S MADebug}
  337. {-----------------------------------+ 
  338. |    ProgramReport                    |
  339. +-----------------------------------}
  340. PROCEDURE ProgramReport (grievance: Str255; break: BOOLEAN);
  341.  
  342. BEGIN
  343.     Writeln(grievance);
  344.     IF break THEN
  345.         TRCBreak;
  346. END {ProgramReport};
  347. {$IFC qTrace}{$D++}{$ENDC}
  348. {$ENDC qDebug}
  349. {$ENDC UsingMacApp}
  350.  
  351.  
  352. {$IFC UsingMacApp}
  353. {$S MAInit}
  354. {$IFC qTrace}{$D+}{$ENDC}
  355. {-----------------------------------+ 
  356. |    SetInitHandler                    |
  357. +-----------------------------------}
  358. PROCEDURE SetInitHandler (handler: ProcPtr);
  359. BEGIN
  360.     gInitHandler := handler;
  361. END {SetInitHandler};
  362. {$IFC qTrace}{$D++}{$ENDC}
  363. {$ENDC UsingMacApp}
  364.  
  365.  
  366. {We assume that the programmer passes in the correct FailInfo record; ie. the one that is the
  367.     top of the stack.}
  368. {$IFC UsingMacApp}
  369. {$S MAMain}
  370. {$ENDC}
  371. {-----------------------------------+ 
  372. |    Success                            |
  373. +-----------------------------------}
  374. PROCEDURE Success (VAR fi: FailInfo);
  375. BEGIN
  376. {$IFC qDebug}
  377.     IF gTopHandler <> @fi THEN
  378.     {$IFC UsingMacApp}
  379.         BEGIN
  380.         Write('gTopHandler = ');
  381.         WritePtr(gTopHandler);
  382.         Write('parameter = ');
  383.         WritePtr(@fi);
  384.         WRITELN;
  385.         ProgramBreak('Problem with Success: too many or too few calls to Success');
  386.         END;
  387.     {$ELSEC UsingMacApp}
  388.         Debugger;
  389.     {$ENDC UsingMacApp}
  390. {$ENDC qDebug}
  391.  
  392.     gTopHandler := fi.nextInfo;
  393. END {Success};
  394.  
  395.